package org.springblade.modules.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.BuildingElevatorDTO;
import org.springblade.modules.admin.entity.ChatGroupBuilding;
import org.springblade.modules.admin.entity.RobotBuildingElevator;
import org.springblade.modules.admin.mapper.RobotBuildingElevatorMapper;
import org.springblade.modules.admin.service.IChatGroupBuildingService;
import org.springblade.modules.admin.service.IRobotBuildingElevatorService;
import org.springblade.modules.admin.vo.BuildingAlreadyVO;
import org.springblade.modules.admin.vo.RobotBuildingElevatorTitleVO;
import org.springblade.modules.admin.vo.RobotBuildingElevatorVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author: Sharry
 * @createTime: 2023/5/18 16:57
 * @version: Version-1.0
 */
@Service
public class RobotBuildingElevatorServiceImpl extends BaseServiceImpl<RobotBuildingElevatorMapper, RobotBuildingElevator> implements IRobotBuildingElevatorService {
	@Autowired
	private IChatGroupBuildingService cgbService;

	@Override
	public boolean addBatch(Long chatgroupId, List<BuildingElevatorDTO> buildingElevatorDTOList) {
		// 将DTO转换为对应实体类
		// 用于接收 项目-电梯列表
		List<RobotBuildingElevator> rbeList = new ArrayList<>();
		// 用于接收 项目id 的Map
		HashMap<Long,Integer> buildingIdMap = new HashMap<>(20);
		// 用于接收 群-项目列表
		List<ChatGroupBuilding> cgbList = new ArrayList<>();

		// 获取已存在的项目-电梯关系
		List<ChatGroupBuilding> list = cgbService.list(new LambdaQueryWrapper<ChatGroupBuilding>().eq(ChatGroupBuilding::getChatgroupId, chatgroupId));
		for (ChatGroupBuilding chatGroupBuilding : list) {
			if(!buildingIdMap.containsKey(chatGroupBuilding.getBuildingId())){
				buildingIdMap.put(chatGroupBuilding.getBuildingId(),1);
			}
		}

		// 遍历赋值
		for (BuildingElevatorDTO buildingElevatorDTO : buildingElevatorDTOList) {
			Long elevatorId = buildingElevatorDTO.getElevatorId();
			Long buildingId = buildingElevatorDTO.getBuildingId();

			ChatGroupBuilding cgb = new ChatGroupBuilding();
			// 去重插入 群-项目 关联表
			if(!buildingIdMap.containsKey(buildingId)){
				buildingIdMap.put(buildingId, 1);
				cgb.setChatgroupId(chatgroupId);
				cgb.setBuildingId(buildingId);
				cgb.setName(buildingElevatorDTO.getBuildingName());
				cgbList.add(cgb);
			}
			List<RobotBuildingElevator> listByConditions = list(new LambdaQueryWrapper<RobotBuildingElevator>()
				.eq(RobotBuildingElevator::getBuildingId, buildingId)
				.eq(RobotBuildingElevator::getElevatorId, elevatorId)
				.eq(RobotBuildingElevator::getChatgroupId, chatgroupId)
			);
			if(Func.isEmpty(listByConditions)){
				RobotBuildingElevator rbe = new RobotBuildingElevator();
				rbe.setChatgroupId(chatgroupId);
				rbe.setBuildingId(buildingId);
				rbe.setElevatorId(elevatorId);
				rbe.setElevatorAddress(buildingElevatorDTO.getElevatorAddress());
				rbeList.add(rbe);
			}
		}
		boolean b = saveBatch(rbeList);
		boolean b1 = cgbService.saveBatch(cgbList);
		// 执行插入操作并返回是否成功
		return b && b1;
	}

	@Override
	public IPage<RobotBuildingElevatorVO> getPageByBuildingId(Long chatgroupId,String elevatorAddress, Long buildingId, IPage<RobotBuildingElevatorVO> page) {
		return baseMapper.getPageByBuildingId(chatgroupId,elevatorAddress,buildingId,page);
	}

	@Override
	public RobotBuildingElevatorTitleVO getTitle(Long chatgroupId) {
		RobotBuildingElevatorTitleVO title = baseMapper.getTitle(chatgroupId);
		// 统计已绑项目数量
		int count = cgbService.count(new LambdaQueryWrapper<ChatGroupBuilding>()
			.eq(ChatGroupBuilding::getChatgroupId, chatgroupId)
		);

		// 统计已绑电梯数量
		List<RobotBuildingElevator> list =
			list(new LambdaQueryWrapper<RobotBuildingElevator>().eq(RobotBuildingElevator::getChatgroupId, chatgroupId));
		int count1 =(int) list.stream().filter(distinctByKey(RobotBuildingElevator::getElevatorId)).count();
		title.setBuildingNum(count);
		title.setElevatorNum(count1);

		return title;
	}

	@Override
	public boolean delByBuildings(Long chatgroupId,List<Long> buildingIds) {
		// 1. 根据 buildingIds 获取 群-项目 关联关系 与 项目-电梯关联关系
		List<Long> chatGroupBuildingIds = new ArrayList<>();
		List<Long> robotBuildingElevatorIds = new ArrayList<>();
		// 遍历获取
		for (Long buildingId : buildingIds) {
			// 赋值，准备删除
			ChatGroupBuilding one = cgbService.getOne(new LambdaQueryWrapper<ChatGroupBuilding>()
				.eq(ChatGroupBuilding::getBuildingId, buildingId)
				.eq(ChatGroupBuilding::getChatgroupId,chatgroupId)
			);

			chatGroupBuildingIds.add(one.getId());

			List<RobotBuildingElevator> list = list(new LambdaQueryWrapper<RobotBuildingElevator>()
				.eq(RobotBuildingElevator::getBuildingId, buildingId)
				.eq(RobotBuildingElevator::getChatgroupId, chatgroupId)
			);

			for (RobotBuildingElevator robotBuildingElevator : list) {
				robotBuildingElevatorIds.add(robotBuildingElevator.getId());
			}

		}

		// 2. 执行 删除
		return cgbService.deleteLogic(chatGroupBuildingIds) && deleteLogic(robotBuildingElevatorIds);
	}

	@Override
	public boolean delByElevators(Long chatgroupId,List<Long> elevatorIds) {
		// 1. 根据 elevatorIds 获取 项目-电梯关联关系
		List<Long> robotBuildingElevatorIds = new ArrayList<>();
		for (Long elevatorId : elevatorIds) {
			RobotBuildingElevator one = getOne(new LambdaQueryWrapper<RobotBuildingElevator>()
				.eq(RobotBuildingElevator::getElevatorId, elevatorId)
				.eq(RobotBuildingElevator::getChatgroupId, chatgroupId)
			);
			robotBuildingElevatorIds.add(one.getId());
		}

		// 2. 执行 删除
		return deleteLogic(robotBuildingElevatorIds);
	}

	@Override
	public List<BuildingAlreadyVO> getLeft(Long chatgroupId) {
		return baseMapper.getLeft(chatgroupId);
	}

	/**
	 * 去重方法
	 * @param keyExtractor 去重依据
	 * @param <T> 占位符
	 */
	public <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
		Map<Object,Boolean> seen = new ConcurrentHashMap<>();
		return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
	}
}
